package org.simp.annotation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.simp.exception.SimpInitException;
import org.simp.service.BaseRunnableService;
import org.simp.util.ClassUtil;

/**
 *@author  zhuhaitao at 2014-6-5
 * 
 **/
public class SimpServiceManager extends BaseRunnableService {

	private static SimpServiceManager manager = new SimpServiceManager();
	
	private Map<String,Object> serviceMap = Collections.synchronizedMap(new HashMap<String,Object>());
	
	private List<BaseRunnableService> runnableList = Collections.synchronizedList(new ArrayList<BaseRunnableService>());
	
	private boolean hasInit ;
	private String scanPacketName;
	private SimpServiceManager(){}
	
	public static SimpServiceManager getInstance(){
		return manager;
	}
	public static SimpServiceManager create(String scanPacketName){
		if(!manager.hasInit){
			manager.scanPacketName = scanPacketName;
			manager.initManager();
		}
		return manager;
	}
	private void initManager(){
		String [] scanPackets = scanPacketName.split(",");
		for(String packetName : scanPackets){
			scanPacketName(packetName);
		}
		start();
		hasInit = true;
	}
	
	public void scanPacketName(String packetName){
		List<Class> classSet = ClassUtil.scanPackage(packetName);
		for(Class<?> clazz : classSet){
			injectService(clazz);
		}
	}
	
	public  void injectService(Class<?> clazz){
		SimpService service = null;
		try{
			service = clazz.getAnnotation(SimpService.class);
		}catch (Exception e) {
			
		}
		if(service != null){
			String simpName = clazz.getSimpleName();
			addService(simpName, clazz);
		}
	}
	
	public void addService(String name,Class<?> clazz){
		if(serviceMap.containsKey(name)){
			throw new SimpInitException( name + " has init ");
		}else{
			
				try {
					Object service = clazz.newInstance();
					serviceMap.put(name, service);
					if(service instanceof BaseRunnableService){
						if(!runnableList.contains(service)){
							runnableList.add((BaseRunnableService)service);
						}
					}
				} catch (InstantiationException e) {
					throw new SimpInitException( name + " is not a class",e);
				} catch (IllegalAccessException e) {
					throw new SimpInitException( name + " no public  constructor",e);
				}
			
		}
	}
	/**
	 * 销毁方法
	 * 
	 * @author zhuhaitao at 2014-6-5
	 */
	public void destroy(){
		for(BaseRunnableService runService :runnableList){
			runService.stop();
		}
		isRun = false;
	}

	@Override
	public void init() {
		for(BaseRunnableService runService :runnableList){
			runService.start();
		}
		
	}

	@Override
	public void alwaysRun() {
		/**检测所有线程服务状态，兵重启关掉的服务**/
		for(BaseRunnableService runService :runnableList){
			Thread thread = runService.getThread();
			if(!thread.isAlive()){
				runService.restart();
			}
		}
		
	}

	@Override
	protected long getPeriod() {
		return 30;
	}
	
	public static <T> T getService (Class<T> clazz){
		return  (T) manager.serviceMap.get(clazz.getSimpleName());
	}
}
